package com.letao.server.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.letao.server.dto.*;
import com.letao.server.entity.*;
import com.letao.server.mapper.SkuInfoMapper;
import com.letao.server.mapper.UserCartInfoMapper;
import com.letao.server.service.*;
import com.letao.server.utils.UserHolderUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    @Resource
    private IOrderDetailService orderDetailService;

    @Resource
    private IOrderStatusLogService orderStatusLogService;

    @Resource
    private IUserCartService userCartService;

    @Resource
    private IOrderService orderService;

    @Resource
    private ISpuService spuService;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private IUserAddressService userAddressService;

    @Resource
    private UserCartInfoMapper userCartInfoMapper;

    @Resource
    private SkuInfoMapper skuInfoMapper;

    @Resource
    private ISkuService skuService;
    @Resource
    private IBaseCategoryService baseCategoryService;
    @Resource
    private ISkuCommentService skuCommentService;
    @Resource
    private IOrderDetailSeckillService orderDetailSeckillService;
    @Resource
    private ISeckillService seckillService;

    /**
     * 新建一个订单 接口等级：用户级
     *
     * @param orderInsertDTO-订单信息
     * @return 返回的结果
     */
    @PostMapping
    private Result insert(@RequestBody OrderInsertDTO orderInsertDTO) {
        log.warn("{}", orderInsertDTO);
        List<UserCartInfo> list = new ArrayList<>();
        UserInfoDTO user = UserHolderUtils.getUser();
        UserAddress userAddress = userAddressService.query().eq("user_id", user.getId()).one();
        if (orderInsertDTO.getOrderInfo().getDeliveryMethod() == 0 && userAddress == null) {
            return Result.fail("用户无地址");
        }
        //1.检测内容是否完整
        if (user.getId() == null ||
                orderInsertDTO.orderInfo.getPaymentMethod() == null || orderInsertDTO.orderInfo.getDeliveryMethod() == null
        ) {
            return Result.fail("数据不完整");
        }

        if (userAddress != null) {
            if (orderInsertDTO.orderInfo.getAddresseeName()==null)
            orderInsertDTO.orderInfo.setAddresseeName(userAddress.getConsigneeName());
            if (orderInsertDTO.orderInfo.getAddresseePhoneNumber()==null)
            orderInsertDTO.orderInfo.setAddresseePhoneNumber(userAddress.getConsigneePhoneNumber());
            if (orderInsertDTO.orderInfo.getAddresseeSex()==null)
            orderInsertDTO.orderInfo.setAddresseeSex(userAddress.getConsigneeSex());
            if (orderInsertDTO.orderInfo.getProvince() == null)
                orderInsertDTO.orderInfo.setProvince(userAddress.getProvinceId());
            if (orderInsertDTO.orderInfo.getCity() == null)
                orderInsertDTO.orderInfo.setCity(userAddress.getCityId());
            if (orderInsertDTO.orderInfo.getDistrict() == null)
                orderInsertDTO.orderInfo.setDistrict(userAddress.getDistrictId());
            if (orderInsertDTO.orderInfo.getDetail() == null)
                orderInsertDTO.orderInfo.setDetail(userAddress.getDetail());
        }

        orderInsertDTO.orderInfo.setUserId(user.getId());
        orderInsertDTO.orderInfo.setOrderStatus(1);

        if (orderInsertDTO.orderList == null)
            orderInsertDTO.orderList = new ArrayList<>();
        if (orderInsertDTO.orderList.isEmpty()) {
            QueryWrapper<UserCartInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", orderInsertDTO.orderInfo.getUserId());
            wrapper.eq("is_order", 0);
            List<UserCartInfo> infoList = userCartInfoMapper.selectList(wrapper);
            for (UserCartInfo info : infoList) {
                orderInsertDTO.orderList.add(info.getId());
            }
        }

        //2.处理订单里的详情
        for (Long id : orderInsertDTO.orderList) {
            UserCartInfo info = userCartService.getById(id);
            if (info == null) {
                return Result.fail("依赖不完整");
            }
            if (info.getIsOrder() == 1) {
                return Result.fail("重复结算");
            }
            list.add(info);
        }
        for (UserCartInfo userCartInfo : list) {
            if (userCartInfo.getNumber() > skuService.getById(userCartInfo.getSkuId()).getStock())
                return Result.fail("商品库存不足");
        }

        //3.处理orderName
        StringBuilder sb = new StringBuilder();
        sb.append(spuService.getById(list.get(0).getSpuId()).getSpuName());
        sb.append(list.get(0).getSkuName());
        if (list.size() != 1)
            sb.append("等");
        orderInsertDTO.orderInfo.setOrderNumber(sb.toString());
        orderService.save(orderInsertDTO.orderInfo);
        orderInsertDTO.orderInfo.setOrderMoney((double) 0);
        Double doublemoney = .0;
        for (UserCartInfo cartInfo : list) {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderInsertDTO.orderInfo.getId());
            orderDetail.setSpuId(cartInfo.getSpuId());
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setAmount(cartInfo.getNumber());


            orderDetail.setTotalMoney(cartInfo.getNumber() * cartInfo.getCartPrice());
            doublemoney += orderDetail.getTotalMoney();
            cartInfo.setIsOrder(1);

            userCartService.updateById(cartInfo);
            orderDetailService.save(orderDetail);
        }
        log.info("用户id={}新增了一个订单,订单id为{}", orderInsertDTO.orderInfo.getUserId(), orderInsertDTO.orderInfo.getId());
        OrderInfo orderInfo = orderService.getById(orderInsertDTO.orderInfo.getId());
        orderInfo.setOrderMoney(doublemoney);
        orderInsertDTO.orderInfo.setOrderMoney(doublemoney);
        orderService.updateById(orderInfo);
        orderStatusLogService.updateState(orderInfo.getId(), orderInfo.getOrderStatus());
        rabbitTemplate.convertAndSend("ttl_exchange", "ttl.message", orderInsertDTO.orderInfo.getId());
        for (UserCartInfo info : list) {
            info.setIsOrder(1);
            userCartService.updateById(info);
        }
        return Result.success(orderInsertDTO);
    }

    @PostMapping("/one")
    private Result buyOne(@RequestBody OrderBuyOneDTO orderBuyOneDTO) {
        if (orderBuyOneDTO.getNumber() == null || orderBuyOneDTO.getSkuId() == null) {
            return Result.fail("数据不完整");
        }
        SkuInfo sku = skuInfoMapper.selectById(orderBuyOneDTO.getSkuId());
        if (sku == null) {
            return Result.fail("依赖不存在");
        }
        if (sku.getStock() < orderBuyOneDTO.getNumber()) {
            return Result.fail("目标商品库存不足");
        }
        sku.setStock(sku.getStock() - orderBuyOneDTO.getNumber());
        skuService.updateById(sku);
        SpuInfo spu = spuService.getById(sku.getSpuId());
        UserInfoDTO user = UserHolderUtils.getUser();
        UserAddress userAddress = userAddressService.query().eq("user_id", user.getId()).one();
        if (userAddress == null && orderBuyOneDTO.getDeliveryMethod() == 0) {
            return Result.fail("用户无地址");
        }
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(user.getId());
        if (userAddress != null) {
            orderInfo.setAddresseeName(userAddress.getConsigneeName());
            orderInfo.setAddresseePhoneNumber(userAddress.getConsigneePhoneNumber());
            orderInfo.setAddresseeSex(userAddress.getConsigneeSex());
            orderInfo.setOrderNumber(spu.getSpuName() + sku.getSkuName());

            BeanUtil.copyProperties(orderBuyOneDTO, orderInfo);
            if (orderInfo.getProvince() == null)
                orderInfo.setProvince(userAddress.getProvinceId());
            if (orderInfo.getCity() == null)
                orderInfo.setCity(userAddress.getCityId());
            if (orderInfo.getDistrict() == null)
                orderInfo.setDistrict(userAddress.getDistrictId());
            if (orderInfo.getDetail() == null)
                orderInfo.setDetail(userAddress.getDetail());
        }

        if (orderBuyOneDTO.getDeliveryMethod() == 1) {
            orderInfo.setShopId(orderBuyOneDTO.getShopId());
        }

        orderInfo.setOrderMoney(sku.getPrice() * orderBuyOneDTO.getNumber());
        orderInfo.setOrderStatus(1);
        orderInfo.setIsSeckill(0);

        orderService.save(orderInfo);

        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(orderInfo.getId());
        orderDetail.setSpuId(spu.getId());
        orderDetail.setSkuId(sku.getId());
        orderDetail.setAmount(orderBuyOneDTO.getNumber());
        orderDetail.setTotalMoney(sku.getPrice() * orderBuyOneDTO.getNumber());

        orderDetailService.save(orderDetail);
        orderStatusLogService.updateState(orderInfo.getId(), orderInfo.getOrderStatus());

        rabbitTemplate.convertAndSend("ttl_exchange", "ttl.message", orderInfo.getId());

        return Result.success(orderInfo.getId());
    }


    /**
     * 修改订单信息 接口等级：管理员
     *
     * @param orderInfo-修改后的订单信息
     * @return 返回的结果
     */
    @PutMapping
    private Result update(@RequestBody OrderInfo orderInfo) {
        //1.检测内容是否完整
        if (orderInfo.getId() == null) {
            return Result.fail("数据不完整");
        }
        if (orderInfo.getOrderStatus() != null && !orderInfo.getOrderStatus().equals(orderService.getById(orderInfo.getId()).getOrderStatus())) {
            orderStatusLogService.updateState(orderInfo.getId(), orderInfo.getOrderStatus());
        }
        orderInfo.setModifiedTime(null);
        orderInfo.setCreateTime(null);
        boolean b = orderService.updateById(orderInfo);
        if (!b) {
            return Result.fail("订单不存在");
        }
        log.info("管理员修改了id={}的订单信息", orderInfo.getId());
        return Result.success();
    }

    /**
     * 用于有条件的分页批量查询订单信息
     * 接口等级：管理员
     *
     * @param userId           用户id
     * @param addresseeName    收件人姓名
     * @param addresseeSex     收件人性别
     * @param provinceId       省级编号
     * @param cityId           市级编号
     * @param districtId       区级编号
     * @param paymentMethod    支付方式
     * @param orderMoneyBottom 范围匹配的最小金额
     * @param orderMoneyTop    范围匹配的最大金额
     * @param orderStatus      订单状态
     * @param deliveryMethod   配送方式
     * @param shopId           取货店铺id
     * @param begin            订单创建开始时间
     * @param end              订单创建结束时间
     * @param isSeckill        是否为秒杀订单
     * @param page             查询页码
     * @param pageSize         查询页的大小
     * @return Result 返回的数据
     */
    @GetMapping("/admin")
    private Result queryPage(
            @RequestParam(required = false) Long orderId,
            @RequestParam(required = false) String userName,
            @RequestParam(required = false) Long userId,
            @RequestParam(required = false) String addresseeName,
            @RequestParam(required = false) Integer addresseeSex,
            @RequestParam(required = false) Integer provinceId,
            @RequestParam(required = false) Integer cityId,
            @RequestParam(required = false) Integer districtId,
            @RequestParam(required = false) Integer paymentMethod,
            @RequestParam(required = false) Double orderMoneyBottom,
            @RequestParam(required = false) Double orderMoneyTop,
            @RequestParam(required = false) Integer orderStatus,
            @RequestParam(required = false) Integer deliveryMethod,
            @RequestParam(required = false) Integer shopId,
            @RequestParam(required = false) String begin,
            @RequestParam(required = false) String end,
            @RequestParam(required = false) Integer isSeckill,
            @RequestParam(required = false) Integer commentState,
            @RequestParam(required = false, defaultValue = "1") Integer page,
            @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
        log.info("管理员批量查询了订单信息");
        return orderService.getPageInfo(orderId, userName, userId, addresseeName, addresseeSex, provinceId,
                cityId, districtId, paymentMethod, orderMoneyBottom, orderMoneyTop, orderStatus,
                deliveryMethod, shopId, begin, end, isSeckill, commentState, page, pageSize);
    }

    /**
     * 分页显示订单中的商品详情
     * 接口等级：管理员
     *
     * @param orderId  订单id
     * @param page     起始页
     * @param pageSize 页大小
     * @return 返回的结果
     */
    @GetMapping("/detail")
    private Result query(@RequestParam Long orderId,
                         @RequestParam(required = false, defaultValue = "1") Integer page,
                         @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
        log.info("查看了订单={}中商品信息", orderId);
        return orderDetailService.getPageInfo(orderId, page, pageSize);
    }


    /**
     * 分页显示订单中的商品详情
     * 接口等级：用户
     *
     * @param orderId  订单id
     * @param page     起始页
     * @param pageSize 页大小
     * @return 返回的结果
     */
    @GetMapping("/detail/user")
    private Result queryDetailUser(@RequestParam Long orderId,
                                   @RequestParam(required = false, defaultValue = "1") Integer page,
                                   @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
        UserInfoDTO user = UserHolderUtils.getUser();
        if (!Objects.equals(user.getId(), orderService.getById(orderId).getUserId()))
            return Result.fail("非本人订单");
        log.info("查看了订单={}中商品信息", orderId);
        return orderDetailService.getPageInfo(orderId, page, pageSize);
    }

    /**
     * 用于有条件的分页批量查询订单信息
     * 接口等级：用户
     *
     * @param orderMoneyBottom 范围匹配的最小金额
     * @param orderMoneyTop    范围匹配的最大金额
     * @param orderStatus      订单状态
     * @param deliveryMethod   配送方式
     * @param shopId           取货店铺id
     * @param begin            订单创建开始时间
     * @param end              订单创建结束时间
     * @param page             查询页码
     * @param pageSize         查询页的大小
     * @return 返回的结果
     */
    @GetMapping("/user")
    private Result queryUser(
            @RequestParam(required = false) Long orderId,
            @RequestParam(required = false) Double orderMoneyBottom,
            @RequestParam(required = false) Double orderMoneyTop,
            @RequestParam(required = false) Integer orderStatus,
            @RequestParam(required = false) Integer deliveryMethod,
            @RequestParam(required = false) Integer shopId,
            @RequestParam(required = false) String begin,
            @RequestParam(required = false) String end,
            @RequestParam(required = false) Integer isSeckill,
            @RequestParam(required = false) Integer commentState,
            @RequestParam(required = false, defaultValue = "1") Integer page,
            @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
        UserInfoDTO user = UserHolderUtils.getUser();
        return orderService.getPageInfo(orderId, null, user.getId(), null, null, null, null, null, null
                , orderMoneyBottom, orderMoneyTop, orderStatus, deliveryMethod, shopId, begin, end, isSeckill, commentState, page, pageSize);
    }

    /**
     * 根据订单id查询具体订单
     * 接口等级:管理员
     *
     * @param orderId 订单id
     * @return
     */
    @GetMapping("/admin/{id}")
    private Result queryById(
            @PathVariable("id") Long orderId
    ) {
        log.info("管理员查询了订单号为{}的订单信息", orderId);
        return orderService.getInfo(orderId);
    }

    /**
     * 根据订单id查询具体订单
     * 接口等级:用户
     *
     * @param orderId 订单id
     * @return
     */
    @GetMapping("/user/{id}")
    private Result queryByIdUser(
            @PathVariable("id") Long orderId
    ) {
        UserInfoDTO user = UserHolderUtils.getUser();
        if (!Objects.equals(user.getId(), orderService.getById(orderId).getUserId()))
            return Result.fail("非本人订单");
        log.info("用户查询了订单号为{}的订单信息", orderId);
        return orderService.getInfo(orderId);
    }

    /**
     * 用于查询特定订单的历史状态
     * 接口等级：用户
     *
     * @param orderId 订单id
     * @return 符合订单状态的list
     */
    @GetMapping("/status/user")
    private Result historyStatusUser(@RequestParam Long orderId) {
        UserInfoDTO user = UserHolderUtils.getUser();
        if (Objects.equals(user.getId(), orderService.getById(orderId).getUserId())) {
            return orderStatusLogService.getListInfo(orderId);
        }
        return Result.fail("订单id错误/非本人订单");
    }

    /**
     * 用于查询特定订单的历史状态
     * 接口等级：管理员
     *
     * @param orderId 订单id
     * @return 符合条件的订单状态list
     */
    @GetMapping("/status")
    private Result historyStatus(@RequestParam Long orderId) {
        return orderStatusLogService.getListInfo(orderId);
    }

    /**
     * 模拟支付接口
     *
     * @param orderId 订单id
     * @return
     */
    @PutMapping("/pay/{orderId}")
    private Result pay(@PathVariable Long orderId) {
        log.info("支付时收到的信息{}", orderId);
        OrderInfo orderInfo = orderService.getById(orderId);

        if (orderInfo == null) {
            return Result.fail("依赖不存在");
        }
        UserInfoDTO user = UserHolderUtils.getUser();
        if (!Objects.equals(user.getId(), orderInfo.getUserId())) {
            return Result.fail("非本人订单");
        }
        orderInfo.setOrderStatus(2);
        orderStatusLogService.updateState(orderId, orderInfo.getOrderStatus());
        orderService.updateById(orderInfo);
        return Result.success();
    }

    /**
     * 已取货接口
     *
     * @param orderId 订单id
     * @return
     */
    @PutMapping("/pick/{orderId}")
    private Result pickUp(@PathVariable Long orderId) {
        OrderInfo orderInfo = orderService.getById(orderId);
        if (orderInfo == null) {
            return Result.fail("依赖不存在");
        }
        UserInfoDTO user = UserHolderUtils.getUser();
        if (!Objects.equals(user.getId(), orderInfo.getUserId())) {
            return Result.fail("非本人订单");
        }
        if (orderInfo.getDeliveryMethod() == 0)
            orderInfo.setOrderStatus(5);
        else
            orderInfo.setOrderStatus(3);
        orderInfo.setDeliveryTime(LocalDateTime.now());
        orderStatusLogService.updateState(orderId, orderInfo.getOrderStatus());
        orderService.updateById(orderInfo);
        return Result.success();
    }

    /**
     * 退货接口
     *
     * @param orderid 订单id
     * @return
     */
    @PutMapping("/return/{orderid}")
    private Result returnOrder(@PathVariable Long orderid) {
        OrderInfo orderInfo = orderService.getById(orderid);
        if (orderInfo == null) {
            return Result.fail("订单不存在");
        }
        UserInfoDTO user = UserHolderUtils.getUser();
        if (!Objects.equals(user.getId(), orderInfo.getUserId())) {
            return Result.fail("非本人订单");
        }
        orderInfo.setOrderStatus(6);
        orderStatusLogService.updateState(orderid, orderInfo.getOrderStatus());
        orderService.updateById(orderInfo);
        return Result.success();
    }

    @GetMapping("/user/detail/new/{id}")
    private Result detailUserNew(@PathVariable Long id){
        OrderInfo orderInfo = orderService.getById(id);
        Map<String,Object> map = new HashMap<>();
        List<BatchOrderDetailDTO> ulist = new ArrayList<>();
        if(orderInfo.getIsSeckill()==0){

            List<OrderDetail> list = orderDetailService.query().eq("order_id", id).list();
            for (OrderDetail detail : list) {
                BatchOrderDetailDTO batchOrderDetailDTO = BeanUtil.copyProperties(detail, BatchOrderDetailDTO.class);
                SkuInfo sku = skuService.getById(batchOrderDetailDTO.getSkuId());
                SpuInfo spu = spuService.getById(batchOrderDetailDTO.getSpuId());
                BaseCategory one = baseCategoryService.getById(spu.getOneCategoryId());
                BaseCategory two = baseCategoryService.getById(spu.getTwoCategoryId());
                batchOrderDetailDTO.setPrice(sku.getPrice());
                batchOrderDetailDTO.setSpuName(spu.getSpuName());
                batchOrderDetailDTO.setSpuImage(spu.getSpuImage());
                batchOrderDetailDTO.setSkuName(sku.getSkuName());
                batchOrderDetailDTO.setSkuImage(sku.getHasImage());
                batchOrderDetailDTO.setOneCategoryId(one.getId());
                batchOrderDetailDTO.setOneCategoryName(one.getName());
                batchOrderDetailDTO.setTwoCategoryId(two.getId());
                batchOrderDetailDTO.setTwoCategoryName(two.getName());
                batchOrderDetailDTO.setDescript(sku.getDescript());
                if (sku.getHasImage() == null) batchOrderDetailDTO.setSkuImage(spu.getSpuImage());
                else batchOrderDetailDTO.setSkuImage(sku.getHasImage());
                SkuCommentInfo comment = skuCommentService.query().eq("sku_id", sku.getId()).eq("order_id", id).one();
                if (comment == null) batchOrderDetailDTO.setCommentStatus(0);
                else batchOrderDetailDTO.setCommentStatus(1);
                ulist.add(batchOrderDetailDTO);
            }

        }else{
            List<OrderDetailSeckill> list = orderDetailSeckillService.query().eq("order_id", id).list();
            for (OrderDetailSeckill orderDetail : list) {
                BatchOrderDetailDTO batchOrderDetailDTO = new BatchOrderDetailDTO();
                batchOrderDetailDTO.setPrice(orderDetail.getConstPrice());
                batchOrderDetailDTO.setTotalMoney(orderDetail.getConstPrice());
                batchOrderDetailDTO.setAmount(1);
                batchOrderDetailDTO.setCommentStatus(0);
                batchOrderDetailDTO.setOrderId(id);
                SeckillInfo seckill = seckillService.getById(orderDetail.getSeckillId());
                batchOrderDetailDTO.setSeckillId(seckill.getId());
                batchOrderDetailDTO.setSpuName(seckill.getName());
                batchOrderDetailDTO.setSpuImage(seckill.getSeckillImage());
                batchOrderDetailDTO.setSkuName(seckill.getName());
                batchOrderDetailDTO.setSkuImage(seckill.getSeckillImage());
                batchOrderDetailDTO.setDescript(seckill.getDescript());
                ulist.add(batchOrderDetailDTO);
            }
        }
        Collections.reverse(ulist);
        map.put("totalSize", ulist.size());
        map.put("detail",ulist);
        map.put("totalMoney",orderInfo.getOrderMoney());
        map.put("orderStatus",orderInfo.getOrderStatus());
        map.put("isSeckill",orderInfo.getIsSeckill());
        return Result.success(map);
    }


}
